/*
* read_route.c
* Sunseker modelling (solar car preformance modelling) project
* This function reads a route file into a route structure.
* A prototype route.dat file:
  
  This is first major revision to this function. First of all, we are now splitting the route.dat file.
  The route.dat file will now only contain data that is constant. This includes gps coordinates, alltitude
  (which will now be generated using a topo program), and other constants. Now, we are storing the things that changes
  in a seperate plan.dat file. This way we can make changes to this file, in order to change the things that vary,
  without generating an entire new route.dat file. For now, we are going to make plan.dat without comments. Later,
  if we wish we can add comments. 

  The first line of plan.dat is ignored and is just used for comments.


*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ssm.h"
#include "ssm_conversions.h"

#define VERSION "0.5"

static int eat_comment(FILE *fp);  // eats commnts and white space
static int line;                   // line in file currently being read.

int read_route(const char *file, const char *plan_file, Route *route) 
{
	FILE *fp;
	FILE *plan;
	int  i;
	char ln[1024];		//for reading comments
	double speed,limit,i_i;	//for comparing the speed with the speed limit

	line=1;

	if((fp=fopen(file,"r")) == NULL) 
	{
		fprintf(stderr,"ERROR: can not open route file %s for input\n", file);
  		exit(1);
	} 
	// Not checking the return value is ok, since on EOF the next call will be EOF too

	if((plan=fopen(plan_file,"r")) == NULL)
	{
		fprintf(stderr,"ERROR: can not open plan file\n"); 

	}

	/*
	For now, a comment is only present on the first line of the plan.dat file. This is a bad idea, because we assume there is a 
	comment on the first line. A future story will be to change this.
	*/
	if((fgets(ln,1024,plan)) == NULL)
	{
		fprintf(stderr,"ERROR: could not read from the plan file\n");
		exit(1);
	}

	eat_comment(fp);
	if(fscanf(fp,"version %20s", route->version) != 1) 
	{
 		fprintf(stderr, "ERROR: in route file %s, line %d, expecting: version <string>\n", file, line);
  		exit(1);
	}

	//

	eat_comment(fp);

	if(fscanf(fp,"comment %200[^#\n]", route->comment) != 1) 
	{
		fprintf(stderr, "ERROR: in route file %s, line %d, expecting: comment <string>\n", file, line);
		exit(1);
	}

	eat_comment(fp);

	if(fscanf(fp,"units %20s", route->units) != 1) 
	{
		fprintf(stderr, "ERROR: in route file %s, line %d, expecting: units [metric | english]\n", file, line);
  		exit(1);
	}

	if((strncmp(route->units,"metric", 6)) && (strncmp(route->units, "english", 7))) 
	{
  		fprintf(stderr, "ERROR: in route file %s, line %d, expecting: units [metric | english]\n", file, line);
  		exit(1);
	}

	eat_comment(fp);
	
	if(fscanf(fp,"nleg %d", &route->nleg) != 1) 
	{
		fprintf(stderr, "ERROR: in route file %s, line %d, expecting: nleg <number>]\n", file, line);
  		exit(1);
	}
	eat_comment(fp);

	if(fscanf(fp,"targetBatt %lf", &route->targetBatt) != 1) 
	{
  		fprintf(stderr, "ERROR: in route file %s, line %d, expecting: targetBatt <number>]\n", file, line);
  		exit(1);
	}
	eat_comment(fp);

	if(fscanf(fp,"targetTime %lf", &route->targetTime) != 1) 
	{
  		fprintf(stderr, "ERROR: in route file %s, line %d, expecting: targetTime <number>]\n", file, line);
  		exit(1);
	}

	if((route->leg = (Leg *)malloc((route->nleg+1)*sizeof(Leg))) == NULL) 
	{
  		fprintf(stderr, "ERROR: in route file %s, Can not malloc space for %d + 1 legs\n", file, route->nleg);
  		exit(1);
	}
	//
	// Read the legs

	for(i=0; i<=route->nleg; i++)  
	{
  		//  # leg distance latitude longitude altitude speed_limit stops hills shade d_x d_y d_z
  		eat_comment(fp);
  
		if(fscanf(fp,"%d %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf",
       			&route->leg[i].i,
       			&route->leg[i].distance,
       			&route->leg[i].latitude,
       			&route->leg[i].longitude,
       			&route->leg[i].altitude,
       			&limit,
       			&route->leg[i].stops,
       			&route->leg[i].hills,
       			&route->leg[i].d_x, 
    			&route->leg[i].d_y, 
			&route->leg[i].d_z,
			&route->leg[i].suntime) != 12) 
			{
				fprintf(stderr, "ERROR: in route file %s, line %d, can not read leg %d\n", file, line, i);
				exit(1);
			}
		
		if(fscanf(plan,"%lf %lf %lf %lf %lf\n",
			&i_i,
			&speed,
			&route->leg[i].windspeed,
			&route->leg[i].windheading,
			&route->leg[i].shade) != 5)
		{
			fprintf(stderr,"ERROR: in plan file on leg %d\n",i);
			exit(1);
		}
		
			route->leg[i].speed=speed;

 		if(route->leg[i].i != i) 
		{
			fprintf(stderr, "ERROR: in route file %s, line %d, expecting leg %d found %d\n", file, line, i, route->leg[i].i);
    			exit(1);
  		}
		if(route->leg[i].i != i_i) 
		{
			fprintf(stderr, "ERROR: in plan file on leg %d\n",i);
    			exit(1);
  		}
	}
	//
	// Check that there is nothing else at the end of the file
	if(eat_comment(fp)!=EOF) 
	{
		fprintf(stderr, "ERROR: in route file %s, line %d, extra lines at end of file\n", file, line);
		exit(1);
	}
	return 0;
}
//
//
// eat_comment() eats white space and commnets, incrementiong
// the line counter as it goes. If one of the fscanfs above
// eats a '\n' between parameters, the line count will be off.
// Perhaps the "line" count is not such a good idea here after all
// That can be fixed if above '\n' is not accepted as a delimiter
// between parameters. hummm....
static int eat_comment(FILE *fp) 
{
	int c;
	// Loop eatting a sequence of optiional white space and comments until
	// either an EOF or a non-comment appears.
	while(1) 
	{
  		// Eat white space, including '\r' for windows...
  		while((c=fgetc(fp)) != EOF) 
		{
    			if((c==' ') || (c=='\t') || (c=='\r')) 
			{
			      continue;
			}
			if(c=='\n') 
			{
				line++;
			 	continue;
			}
			break;
		}
		if(c==EOF)
		{
			return EOF;
		}
		// It was not a comment, so push the byte back and return.
		if(c!='#')
		{
			ungetc(c,fp);
			return 0;
		}
		// Eat the comment, 'till the end of the line.
		while((c=fgetc(fp)) != EOF) 
		{
			if(c=='\n') 
			{
				line++;
				break;
			}
		}
		if(c==EOF) 
		{
    			return EOF;
		}
	}
	// You should never get here.
	return -2;
}
